/**
 * @author 14544
 * @date 2020/4/1 11:51
 */
// 断点续传的前端代码

// 想要恢复文件上传，关键在于要知道我们已经上传了多少或者说服务器接收了多少
// 虽然我们可以有 xhr.upload.onprogress 方法监听上传的进度，不幸的是，它在这里没什么作用，它在数据发送 send 完成时触发，但是它真的被服务器接收了吗？浏览器并不知道。
// 或许它只是被本地代理缓冲（buffered），或是有可能远程服务器处理进程宕机无法处理它们，亦或是当连接断开时它刚刚从中间丢失，且没有到达服务器。
// 因此，这个事件只是对于显示一个漂亮的进度条来说很有用。
// 要恢复上传，我们需要知道服务器具体接收了多少字节。只有服务器能告诉我们它接收了多少。

// 第一步：定义一个请求获取的文件已上传的字节长度
{
    (async function getUploadedBytes() {
        // 可以定义一个唯一的文件标识，让后端知道这个文件是否已经上传过
        let file = {} // 假如这是要上传的文件对象
        let fileId = `${file.name}-${file.size}-${file.lastModifiedDate}` ;
        let res = await fetch('/uploadedBytes',{
            headers:{
                "X-FILE-ID":fileId // 这假设服务器通过 X-File-Id 头跟踪文件上传。应该在服务端实现。可以根据前后端约定，制定不同的方案
            }
        })
        // 服务器已有的字节
        let startBytes = + await res.text()
    })()
}

// 第二步：获取到已有的字节，可以正常的进行上传
{
    let fileId = 'xxx'; // 假如这是约定的文件id
    let startBytes = 'xxx'; // 假如已经获取到已上传的字节数
    let xhr = new XMLHttpRequest();
    xhr.open('POST','/upload',true);
    // 发送文件 id，这样服务器就能知道要恢复哪个文件
    xhr.setRequestHeader('X-FILE-ID',fileId)
    // 发送我们正在恢复的字节，因此服务器知道我们正在恢复文件
    // 服务器应该检查它的记录，如果这个文件之前上传过且当前上传大小是 X-Start-Byte，此时将数据附加到原来文件上。
    xhr.setRequestHeader('X-START-BYTES',startBytes)
    xhr.upload.onload = function (e) {
        console.log('上传成功')
    }
    // 因为文件的长度从服务器已经获取的地方截取，将剩余的上传，所以服务器返回的是剩余的长度值，为了让进度条正确的显示，手动加上之前的长度
    xhr.upload.onprogress = function (e) {
        console.log("上传进度：",e.loaded + startBytes/e.total+startBytes)
    }
    let formData = new FormData()
    // 使用slice方法，将文件的长度从服务器已经获取的地方截取，将剩余的上传
    formData.append('file',file.slice(startBytes+1))
    xhr.send(formData)
}